package com.lik888.web1.Aspect;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.lik888.web1.Log.Log;
import com.lik888.web1.constants.UserContext;
import com.lik888.web1.entity.LogTable;
import com.lik888.web1.mapper.LogTableMapper;
import lombok.RequiredArgsConstructor;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;

import static com.lik888.web1.constants.AOPContext.EXPRESSION;

//声明当前类为Aspect切面，并交给Spring容器管理
@Component
@Aspect
@RequiredArgsConstructor
@Order(1)
public class AspectJAspect {
    private final LogTableMapper logTableMapper;

    @Pointcut(EXPRESSION)
    public void logPointcut(Log log) {
    }
    //前置通知   
//    @Before(EXPRESSION)
//    public void beforeAdvice(JoinPoint joinPoint){
//        System.out.println("========== 【Aspectj前置通知】 ==========");
//    }


//    //后置通知：方法正常执行后，有返回值，执行该后置通知：如果该方法执行出现异常，则不执行该后置通知
//    @AfterReturning(value = EXPRESSION,returning = "returnVal")
//    public void afterReturningAdvice(JoinPoint joinPoint,Object returnVal){
//      System.out.println("========== 【Aspectj后置通知】 ==========");
//    }
//
//    //后置通知
//    @After(EXPRESSION)
//    public void afterAdvice(JoinPoint joinPoint){
//    }

    //环绕通知
    @Around(EXPRESSION)
    public Object aroundAdvice(ProceedingJoinPoint joinPoint ,Log log) throws Throwable {
        System.out.println("##########【环绕通知中的环绕通知】##########");
        //1.1 获取方法名
        LogTable logTable = new LogTable();
        String methodName = joinPoint.getSignature().getName();
        String logPart = log.part();
        //当前时间
        LocalDateTime logTime = LocalDateTimeUtil.now();
//        System.out.println("##########【环绕通知中的前置通知】##########");
        Object returnVale = joinPoint.proceed();
        //执行结束后时间
        LocalDateTime endTime = LocalDateTimeUtil.now();
        //执行时间
        long durationMs = LocalDateTimeUtil.between(logTime, endTime, ChronoUnit.MILLIS);
        Long userId = UserContext.getUser();
// 转换为“秒”（保留1位小数，如 0.5秒；如果是0毫秒则显示0秒）
        String durationStr = durationMs == 0 ? "0秒" : (durationMs / 1000.0) + "秒";
        logTable.setLogMethodname(methodName);
        logTable.setLogUser(userId);
        logTable.setLogTime((int) durationMs);
        logTable.setLogPart(logPart);
        logTable.setLogPart(returnVale.toString());
        logTableMapper.insert(logTable);
        System.out.println("##########【环绕通知中的后置通知】##########");
        return returnVale;
    }

    // 异常通知：方法出现异常时，执行该通知
    @AfterThrowing(value = EXPRESSION,throwing = "ex")
    public void throwAdvice(JoinPoint joinPoint, Exception ex){
        System.out.println("********** 【Aspectj异常通知】执行开始 **********");
        System.out.println("出现异常：" + ex.getMessage());
        System.out.println("********** 【Aspectj异常通知】执行结束 **********");
    }

}